package com.vista.beans.obra;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import javax.annotation.PostConstruct;
import javax.faces.application.FacesMessage;
import javax.faces.application.FacesMessage.Severity;
import javax.faces.context.FacesContext;
import javax.faces.event.ActionEvent;

import org.primefaces.model.DualListModel;
import org.primefaces.model.LazyDataModel;
import org.primefaces.model.SortOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

import com.comun.filtro.FiltroLista;
import com.facade.documento.IGestionDocumento;
import com.facade.obra.IGestionObra;
import com.facade.utils.UtilsFacade;
import com.modelo.entity.Documento;
import com.modelo.entity.Obra;
import com.modelo.entity.ObraDocumento;
import com.vista.utils.UtilsWeb;

/**
 * Bean encargado de la vista de obras.
 * 
 * @author David
 * 
 */
@Component
@Scope("request")
public class ObraBean implements Serializable {
	// TODO tener cuidado al sustituir por lo que hay arriba.
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;

	private String buttonText = "Crear";
	private String cliente;
	private List<Documento> docSeleccionados;
	private DualListModel<Documento> dualListDocumento;
	// Customizacion de la vista.
	private String header = "Nueva Obra";
	private Integer id;
	@Autowired
	private IGestionDocumento iGestionDocumento;
	@Autowired
	private IGestionObra iGestionObra;

	// ////////////////////////////////// obraEliminar.xhtml
	@Autowired
	@Qualifier("LazyObraDataModel")
	private LazyDataModel<Obra> lazyObras;
	private List<Documento> listaDocActivos;

	private String nombre;
	// private Set<ObraProveedor> obraProveedors = new
	// HashSet<ObraProveedor>(0);
	private Set<ObraDocumento> obraDocumentos;

	// ////////////////////////////////// obraModificar.xhtml
	private Obra obraModificar;

	private Obra[] obraSeleccionados;

	private String poblacion;

	/**
	 * Se encarga de cargar los documentos activos en dicha lista. Este metodo
	 * se ejecutara nada mas crearse este Bean.
	 */
	@PostConstruct
	public void cargarDatos() {
		FiltroLista filtro = new FiltroLista(null, null, UtilsFacade.convertSortOrderToOrder(
				SortOrder.ASCENDING, "nombre"), null);

		// if (listaDocActivos == null || listaDocActivos.isEmpty()) {
		listaDocActivos = iGestionDocumento.getDocumentosActivos(filtro);
		// }

		// if (docSeleccionados == null || docSeleccionados.isEmpty()) {
		docSeleccionados = new ArrayList<Documento>();
		// }

		dualListDocumento = new DualListModel<Documento>(listaDocActivos, docSeleccionados);
	}

	/**
	 * Evento del boton crear, que recoge los valores de la vista y crea la
	 * obra.
	 * 
	 * @param event
	 */
	public void crear(ActionEvent event) {
		// Message to show
		String messageHeader = "Obra Creada Correctamente";
		String messageBody = "Creado Correctamente";
		Severity kindMessage = FacesMessage.SEVERITY_INFO;
		String idMessages = "informacion";

		docSeleccionados = dualListDocumento.getTarget();

		if (docSeleccionados != null && !docSeleccionados.isEmpty()) {
			try {
				Obra obra = new Obra();
				obra.setCliente(getCliente());
				obra.setFechaAlta(new Date());
				obra.setNombre(getNombre());
				obra.setPoblacion(getPoblacion());
				obraDocumentos = new HashSet<ObraDocumento>(0);

				// from view came with id=0
				if (id != null && !id.equals(new Integer(0))) {
					// Update
					obra.setId(id);
					iGestionObra.attachDocumentos(obra);

					// obra.setObraDocumentos(iGestionObra.getObraDocumentosUpdated(UtilsWeb.obtenerIdsLista(docSeleccionados),
					// obra));

					iGestionObra.actualizar(obra);

					messageHeader = "Obra Modificada Correctamente";
					messageBody = "Modificada Correctamente";
					// resetValues();

					setButtonText("Modificar");
					setHeader("Modificar Obra");
				} else {
					// Create
					for (Documento documento : docSeleccionados) {
						ObraDocumento obraDocumento = new ObraDocumento();
						obraDocumento.setDocumento(documento);
						obraDocumento.setFechaAlta(new Date());
						obraDocumento.setObra(obra);
						obraDocumentos.add(obraDocumento);
					}
					obra.setObraDocumentos(obraDocumentos);

					iGestionObra.crear(obra);
					resetValues();
					cargarDatos();

				}

				// resetValues();
			} catch (Exception e) {
				e.printStackTrace();
				// TODO: mirar la excepcion que es y mandar por email.
				kindMessage = FacesMessage.SEVERITY_ERROR;
				messageHeader = "Error Creacion Obra";
				messageBody = "Obra NO Creada";
			}
		} else {
			dualListDocumento = new DualListModel<Documento>(listaDocActivos, docSeleccionados);
			kindMessage = FacesMessage.SEVERITY_ERROR;
			messageHeader = "Error Creacion Obra";
			messageBody = "Debe seleccionar los documentos correspondientes a esta obra.";
		}

		FacesContext.getCurrentInstance().addMessage(idMessages,
				new FacesMessage(kindMessage, messageHeader, messageBody));

	}

	public void eliminarObras() {
		try {
			if (obraSeleccionados != null && obraSeleccionados.length > 0) {
				List<Obra> obrasEliminar = Arrays.asList(obraSeleccionados);
				iGestionObra.delete(obrasEliminar);

				FacesContext.getCurrentInstance().addMessage(
						"informacion",
						new FacesMessage(FacesMessage.SEVERITY_INFO, "Obras Eliminadas: ",
								"En total se han eliminado " + obrasEliminar.size() + " obras."));
			}
		} catch (Exception e) {
			// TODO: handle exception Enviar email diciendo el error.
			FacesContext
					.getCurrentInstance()
					.addMessage(
							"informacion",
							new FacesMessage(FacesMessage.SEVERITY_ERROR, "Obras Eliminadas: ",
									"Se produjo un error al eliminar las obras con los siguientes IDs -> "));
			e.printStackTrace(); // TODO Borrar pasado un tiempo
			// TODO falta poner los ids q se eliminan.
		}
	}

	/**
	 * @return the buttonText
	 */
	public String getButtonText() {
		return buttonText;
	}

	/**
	 * @return the cliente
	 */
	public String getCliente() {
		return cliente;
	}

	/**
	 * @return the dualListDocumento
	 */
	public DualListModel<Documento> getDualListDocumento() {
		return dualListDocumento;
	}

	/**
	 * @return the header
	 */
	public String getHeader() {
		return header;
	}

	/**
	 * @return the id
	 */
	public Integer getId() {
		return id;
	}

	/**
	 * @return the iGestionDocumento
	 */
	public IGestionDocumento getiGestionDocumento() {
		return iGestionDocumento;
	}

	/**
	 * @return the iGestionObra
	 */
	public IGestionObra getiGestionObra() {
		return iGestionObra;
	}

	/**
	 * @return the lazyObras
	 */
	public LazyDataModel<Obra> getLazyObras() {
		return lazyObras;
	}

	/**
	 * @return the listaDocActivos
	 */
	public List<Documento> getListaDocActivos() {
		return listaDocActivos;
	}

	/**
	 * @return the nombre
	 */
	public String getNombre() {
		return nombre;
	}

	/**
	 * @return the obraDocumentos
	 */
	public Set<ObraDocumento> getObraDocumentos() {
		return obraDocumentos;
	}

	/**
	 * @return the obraModificar
	 */
	public Obra getObraModificar() {
		return obraModificar;
	}

	/**
	 * @return the obraSeleccionados
	 */
	public Obra[] getObraSeleccionados() {
		return obraSeleccionados;
	}

	/**
	 * @return the poblacion
	 */
	public String getPoblacion() {
		return poblacion;
	}

	public String modificar() {
		nombre = obraModificar.getNombre();
		cliente = obraModificar.getCliente();
		poblacion = obraModificar.getPoblacion();
		id = obraModificar.getId();
		// necesitamos traernos los documentos asociados a la obra,
		// puesto q los demas datos los tenemos.
		obraModificar = iGestionObra.attachDocumentos(obraModificar);
		docSeleccionados = UtilsWeb.getDocumentos(obraModificar);

		/*
		 * Esto hay que meterlo en algun lado public List<Documento>
		 * getDocumentos() { List<Documento> listaDoc = new
		 * ArrayList<Documento>();
		 * 
		 * for (Iterator<ObraDocumento> it = obraDocumentos.iterator();
		 * it.hasNext();) { ObraDocumento obraDocumento = it.next();
		 * listaDoc.add(obraDocumento.getDocumento()); } return listaDoc; }
		 */

		// tenemos que obtener la lista de DocActivos, pero hay que quitar
		// los doc asociados a la obra. Solucion:
		// 1- ir a base de datos y traerse los docActivos no asociados
		// 2- crearnos un metodo y hacerlo manualmente.
		// decidimos ir a base de datos.
		dualListDocumento = new DualListModel<Documento>(
				iGestionDocumento.getDocumentosActivosAExcepcion(docSeleccionados),
				docSeleccionados);

		// docSeleccionados = obraModificar.getObraDocumentos();

		// Customizacion de la vista
		buttonText = "Modificar";
		header = "Modificar Documento";

		return "obraNueva";
	}

	/**
	 * Metodo que recarga la informacion en la duallist de documentos
	 */
	public void recargarDualListDocumento() {
		// Cuando crea/modifica en la dual list solo tiene los documentos con
		// los id, no tiene
		// el nombre de los documentos por eso tenemos que traernos de base de
		// datos.
		List<Integer> listaIdsActivos = UtilsWeb.obtenerIdsLista(dualListDocumento.getSource());
		List<Integer> listaIdsSeleccionados = UtilsWeb.obtenerIdsLista(dualListDocumento
				.getTarget());

		dualListDocumento.setSource(iGestionDocumento.findByListId(listaIdsActivos));
		dualListDocumento.setTarget(iGestionDocumento.findByListId(listaIdsSeleccionados));

	}

	private void resetValues() {
		id = null;
		nombre = "";
		cliente = "";
		poblacion = "";
		// recargarDualListDocumento();
	}

	/**
	 * @param buttonText
	 *            the buttonText to set
	 */
	public void setButtonText(String buttonText) {
		this.buttonText = buttonText;
	}

	/**
	 * @param cliente
	 *            the cliente to set
	 */
	public void setCliente(String cliente) {
		this.cliente = cliente;
	}

	/**
	 * @param dualListDocumento
	 *            the dualListDocumento to set
	 */
	public void setDualListDocumento(DualListModel<Documento> dualListDocumento) {
		this.dualListDocumento = dualListDocumento;
	}

	/**
	 * @param header
	 *            the header to set
	 */
	public void setHeader(String header) {
		this.header = header;
	}

	/**
	 * @param id
	 *            the id to set
	 */
	public void setId(Integer id) {
		this.id = id;
	}

	/**
	 * @param iGestionDocumento
	 *            the iGestionDocumento to set
	 */
	public void setiGestionDocumento(IGestionDocumento iGestionDocumento) {
		this.iGestionDocumento = iGestionDocumento;
	}

	/**
	 * @param iGestionObra
	 *            the iGestionObra to set
	 */
	public void setiGestionObra(IGestionObra iGestionObra) {
		this.iGestionObra = iGestionObra;
	}

	/**
	 * @param lazyObras
	 *            the lazyObras to set
	 */
	public void setLazyObras(LazyDataModel<Obra> lazyObras) {
		this.lazyObras = lazyObras;
	}

	/**
	 * @param listaDocActivos
	 *            the listaDocActivos to set
	 */
	public void setListaDocActivos(List<Documento> listaDocActivos) {
		this.listaDocActivos = listaDocActivos;
	}

	/**
	 * @param nombre
	 *            the nombre to set
	 */
	public void setNombre(String nombre) {
		this.nombre = nombre;
	}

	/**
	 * @param obraDocumentos
	 *            the obraDocumentos to set
	 */
	public void setObraDocumentos(Set<ObraDocumento> obraDocumentos) {
		this.obraDocumentos = obraDocumentos;
	}

	/**
	 * @param obraModificar
	 *            the obraModificar to set
	 */
	public void setObraModificar(Obra obraModificar) {
		this.obraModificar = obraModificar;
	}

	/**
	 * @param obraSeleccionados
	 *            the obraSeleccionados to set
	 */
	public void setObraSeleccionados(Obra[] obraSeleccionados) {
		this.obraSeleccionados = obraSeleccionados;
	}

	/**
	 * @param poblacion
	 *            the poblacion to set
	 */
	public void setPoblacion(String poblacion) {
		this.poblacion = poblacion;
	}

}
